package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * 自动填充注解的切面
 */
@Aspect
@Component // 需要将该类加入到IOC容器中
@Slf4j
public class AutoFillAspect {

    //定义切点，这里使用注解的方式来定义切点，根据需要自行设置
    @Pointcut("execution(public * com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointcut() {}

    // 定义前置通知，使用在方法aspect()上注册的切入点
    @Before("autoFillPointcut()")
    public void autoFill(JoinPoint joinPoint) {
        log.info("开始自动填充。。。");

            //通过反射获取目标对象关联的注解值
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            AutoFill autoFill = methodSignature.getMethod().getAnnotation(AutoFill.class);
            OperationType value = autoFill.value();

            //获取参数--实体对象
            Object[] args = joinPoint.getArgs();
            Object target = args[0];
            if (target == null){
                return;
            }

            //准备填充的数据
            LocalDateTime now = LocalDateTime.now();
            Long currentId = BaseContext.getCurrentId();

            //根据填充类型进行字段填充
            if (value == OperationType.INSERT){
                try {
                    //通过反射填充创建人、创建时间，修改人，修改时间
                    Method setCreateTime = target.getClass().getMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                    Method setCreateUser = target.getClass().getMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                    Method setUpdateTime = target.getClass().getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                    Method setUpdateUser = target.getClass().getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

                    //设置值
                    setUpdateUser.invoke(target, currentId);
                    setUpdateTime.invoke(target, now);
                    setCreateTime.invoke(target, now);
                    setCreateUser.invoke(target, currentId);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else if (value == OperationType.UPDATE){
                try {
                    //填充更新人、更新时间
                    Method setUpdateTime = target.getClass().getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                    Method setUpdateUser = target.getClass().getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

                    //设置值
                    setUpdateUser.invoke(target, currentId);
                    setUpdateTime.invoke(target, now);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

    }



}
